import { Logger as LoggerExtension } from '@hocuspocus/extension-logger';
import { Server } from '@hocuspocus/server';
import { Redis } from '@hocuspocus/extension-redis';
import express from 'express';
import expressWebsockets from 'express-ws';
import dotenv from 'dotenv';
import { logger } from './logger.js';
import queryReviewService from './review/queryReviewService.js';
import verifyTokenService from './auth/verifyTokenService.js';

dotenv.config();

const server = Server.configure({
  extensions: [
    new Redis({
      // 同步负载均衡多实例的数据
      host: process.env.REDIS_HOST,
      port: parseInt(process.env.REDIS_PORT, 10),
      options: {
        db: parseInt(process.env.REDIS_DB, 10),
      },
    }),
    new LoggerExtension({
      onChange: false,
      onStoreDocument: false,
      log: (message) => {
        logger.info(message);
      },
    }),
  ],
  async onAuthenticate(data) {
    const { token, context } = data;
    context.token = token;
    const user = await verifyTokenService(token);
    return {
      token,
      user,
    };
  },
  async onLoadDocument(payload) {
    const document = await queryReviewService.attach(payload);
    return document;
  },
  async onStateless({ document, payload }) {
    try {
      const message = JSON.parse(payload);
      if (message.type === 'broadcast') {
        document.broadcastStateless(payload);
        logger.info('broadcast', payload);
      }
      if (message.type === 'refreshData') {
        queryReviewService.attach({ documentName: document.name, document, context: { token: message.token } });
        logger.info('refreshData', payload);
      }
    } catch (e) {
      logger.error(e);
    }
  },
});

const { app } = expressWebsockets(express());
app.use(express.json());

app.post('/test', (request, response) => {
  logger.info('test', request.body); // 打印请求体，仅自测时使用，部署后使用正式接口，在env中配置
  response.sendStatus(200);
});

app.get('/test', (request, response) => {
  logger.info('test', request.body); // 打印请求体，仅自测时使用，部署后使用正式接口，在env中配置
  response.send([{ descriptions: 'test' }, { descriptions: 'test2222' }]); // 修改为返回 JSON 响应
});

// 健康检查使用
app.get('/health', (_, response) => {
  response.sendStatus(200);
});

app.ws('/syncReviewData', (websocket, request) => {
  logger.info(`connected: ${request.query?.user} || ${request.query?.type} || ${request.query?.id}`);
  // 添加错误监听器，捕获并处理 WebSocket 错误，防止服务崩溃
  websocket.on('error', (error) => {
    logger.error('WebSocket 连接错误:', error);
    logger.error(`error from: ${request.query?.user} || ${request.query?.type} || ${request.query?.id}`);
    // 可选：关闭错误的连接，并返回相应的关闭码及原因
    websocket.close(1002, 'Invalid WebSocket frame');
  });

  // 继续处理连接
  server.handleConnection(websocket, request);
});

app.listen(1234, () => console.log('Listening on http://127.0.0.1:1234…'));
